﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAL;
using System.Data;
using System.IO;
using System.Configuration;
using System.Transactions;
using System.Data.Linq;
using System.ComponentModel;
using UtilityExtensions;
using BOL.CentroCosto;


namespace BOL
{
    public class RendicionBL
    {
        public int Add(string descripcion,
                       int idObra,
                        int idCaja,
                         DateTime fechaDeposito,
                        int idTipoEntregaDeposito,
                        string numDocumentoDeposito,
                        decimal totalDeposito
                        )
        {



            

            using (TransactionScope ts = new TransactionScope())
            {

                dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString);
                DAL.Rendicion a = new DAL.Rendicion();
                int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());
                
                short itemAnterior=a.GetUltimoItemRendicion(_db,idCaja);
                

                decimal saldoAnterior=0;
                var rendicionAnterior = _db.Rendicions.SingleOrDefault(p => p.idCaja == idCaja & p.itemRendicion == itemAnterior);
                
                short itemActual = itemAnterior += 1;

                if (rendicionAnterior != null)
                {   // la caja anterior debe estar cerrada para continuar

                    if (rendicionAnterior.idEstado != 41 & rendicionAnterior.idEstado != 42)
                    {
                        throw new Exception("No puede Aperturar otra Rendición si la anterior no fue aun  Cerrado");
                    }
                    saldoAnterior = rendicionAnterior.totalSaldo;
                }

                a.SetAdd(_db,
                    null,
                    a.getCorrelativo(_db, idCaja),
                    descripcion,
                    39,
                    idObra,
                    idCaja,
                    itemActual,
                    saldoAnterior,
                    idEmpleadoEmisor);
                
                _db.SubmitChanges();

               
                         
                this.AddDeposito(_db,
                    a.idInternal,
                    fechaDeposito,
                    idTipoEntregaDeposito,
                    numDocumentoDeposito,
                    totalDeposito
                    );
                                              ts.Complete();
               
                return a.idInternal;
            }


        }


        public void HabilitadoToDeposito(dbGestionDataContext _db,int idObra)
        {
            //tiene que tener acceso a crear depositos
            int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

            var w = from a in _db.EmpleadoObras
                    where a.idObra == idObra & a.idEmpleado == idEmpleadoEmisor
                    select a.Rol;

            if (w.Count() == 0)
            {
                throw new Exception("No tiene acceso a la Obra");
            }

            Rol rol = w.First();

            if (!rol.bitDepositoRendicionC)
            {
                throw new Exception("El usuario no  esta habilitado para realizar el Deposito");
            }

        }

        public int AddDeposito(dbGestionDataContext _db,
                                int idRendicion,
                                DateTime fecha,
                                int idTipoEntrega,
                                string numDocumento,
                                decimal total)
        {
            using (TransactionScope ts= new TransactionScope())
            {
                int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());
                var rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);


               this.HabilitadoToDeposito(_db,rendicion.idObra);
                    // la rendicion no debe estar aprobada

                    if (rendicion.idEstado != 39)
                    {
                        throw new Exception("No puede ingresar depositos verifique  Estado de la Recepcion");
                    }

              //------------------------------------------------------
                var rendicionDeposito = new RendicionDeposito();
                rendicionDeposito.SetAdd(
                                _db,
                                idRendicion,
                                fecha,
                                idTipoEntrega,
                                numDocumento,
                                total,
                                idEmpleadoEmisor
                                );

                //actualiza la cab
                _db.SubmitChanges();

                rendicion.updateTotal(_db);
                _db.SubmitChanges();

                ts.Complete();
                return rendicionDeposito.idInternal;
            }
        }


        public int AddRendicionItem(
                                    DateTime fecha,
                                    int tipoDocumento,
                                    string nroDocumento,
                                    string descripcion,
                                    string concepto,
                                    decimal total,
                                    decimal igv,    //18 or 19% 
                                    int idGrupo,
                                    int idRendicion,
                                    int? idProveedorOrEmpleado,
                                    string tipobeneficiario
                                    )
        {
            

            using (TransactionScope ts=new TransactionScope())
            {
                dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString);
                int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                Rendicion rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);



                Moneda monedaAct = _db.Monedas.Single(p => p.idInternal == 4);
                decimal tp = monedaAct.getTipoCambio(_db, fecha);


                int? idProveedor=null;
                int? idEmpleado=null;

                if (tipobeneficiario == "EMPLEADO")
                {
                    idEmpleado = idProveedorOrEmpleado;
                    if (idEmpleado == null)
                    {
                        throw new Exception("Debe ingresar la informacin del Empleado");
                    }
                    
                }
                else
                {

                    idProveedor = idProveedorOrEmpleado;
                    if (idProveedor == null)
                    {
                        throw new Exception("Debe ingresar la informacin del proveedor");
                    }
                }
                //convertimos segun moneda a  soles
                //-------------------------------------
                decimal totalcal = total;
                if (rendicion.Caja.idMoneda == 4)
                {
                    totalcal = Math.Round(total/tp,2);
                }


                decimal renta4ta =0;
                if (totalcal >= 1500 & tipoDocumento==3) //honorarios
                    {
                        renta4ta = total * 0.1m;
                    }
                    
                //---------------------------------------- FACTURA
                decimal totalIGV = 0;
                if (tipoDocumento == 2)
                {
                   totalIGV=Math.Round(total * (1 + igv / 100)-total,2);
                }
                
                var rendicionItem = new RendicionItem();
                rendicionItem.SetAdd(_db,
                                fecha,
                                null,
                                null,
                                tipoDocumento,
                                nroDocumento,
                                descripcion,
                                concepto,
                                total,
                                totalIGV,
                                renta4ta,
                                idGrupo,
                                idProveedor,
                                idEmpleado,
                                idRendicion,
                                idEmpleadoEmisor);
                _db.SubmitChanges();
                rendicion.updateTotal(_db);
                _db.SubmitChanges();
                ts.Complete();
                return rendicionItem.idInternal;
            }
          

        }

        public void UpdateDeposito(int idRendicionDeposito, 
                                    DateTime fecha, 
                                    int idTipoEntrega, 
                                    string numDocumento,
                                    decimal total)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                var _db = new dbGestionDataContext(Parametros.strConnString);
                int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());
                var rendicionDeposito = _db.RendicionDepositos.Single(p => p.idInternal == idRendicionDeposito);
                var rendicion = _db.Rendicions.Single(p => p.idInternal == rendicionDeposito.idRendicion);


                //tiene que tener acceso a crear depositos
                var w = from a in _db.EmpleadoObras
                        where a.idObra == rendicion.idObra & a.idEmpleado == idEmpleadoEmisor
                        select a.Rol;

                if (w.Count() == 0)
                {
                    throw new Exception("No tiene acceso a la Obra");
                }

                Rol rol = w.First();

                if (!rol.bitDepositoRendicionC)
                {
                    throw new Exception("El usuario no  esta habilitado para Actualizar la Depositos");
                }


                //------------------------------------------------------

                rendicionDeposito.SetUpdate(
                                fecha,
                                idTipoEntrega,
                                numDocumento,
                                total,
                                idEmpleadoEmisor
                                );

                //actualiza la cab
                _db.SubmitChanges();
                rendicion.updateTotal(_db);
                _db.SubmitChanges();
                ts.Complete();
               
              
            }
        }

        public void Delete(int idrendicion)
        {

            using (TransactionScope ts = new TransactionScope())
            {
                dbGestionDataContext _db= new dbGestionDataContext(Parametros.strConnString);

                var rendicion = _db.Rendicions.Single(p => p.idInternal == idrendicion);
                //solo puede eliminar el ultimo registro
                short itemUltimo=rendicion.GetUltimoItemRendicion(_db, rendicion.idCaja);

                if (rendicion.itemRendicion!=  itemUltimo)
                    throw new Exception("Solo puede eliminar la ultima rendicion Activa");


                if (rendicion.idEstado == 42)
                {
                    throw new Exception("Verifique estado de la Rendicion de Caja");
                }
                _db.RendicionItems.DeleteAllOnSubmit(rendicion.RendicionItems);
                _db.RendicionGrupos.DeleteAllOnSubmit(rendicion.RendicionGrupos);
                _db.RendicionDepositos.DeleteAllOnSubmit(rendicion.RendicionDepositos);
                _db.Rendicions.DeleteOnSubmit(rendicion);
                _db.SubmitChanges();
                ts.Complete();

            }
            

        }

        public void DeleteDeposito(int idRendicionDeposito)
        {

            using (TransactionScope ts = new TransactionScope())
            {
                var _db = new dbGestionDataContext(Parametros.strConnString);

                var rendicionDeposito = _db.RendicionDepositos.SingleOrDefault(p => p.idInternal == idRendicionDeposito);
                var rendicion = _db.Rendicions.Single(p => p.idInternal == rendicionDeposito.idRendicion);

                _db.RendicionDepositos.DeleteOnSubmit(rendicionDeposito);
                _db.SubmitChanges();
                rendicion.updateTotal(_db);
               
                _db.SubmitChanges();   
                ts.Complete();
            }
        }
        public void DeleteRendicionItem(int idRendicionItem)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString);
                var rendicionItem = _db.RendicionItems.SingleOrDefault(p => p.idInternal == idRendicionItem);
                var rendicion = _db.Rendicions.Single(p => p.idInternal == rendicionItem.idRendicion);

                _db.RendicionItems.DeleteOnSubmit(rendicionItem);
                _db.SubmitChanges();

                rendicion.updateTotal(_db);

                _db.SubmitChanges();
                ts.Complete();

            }
        }

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public IEnumerable<RendicionItemInfo> getRecepcionItemList(int idRendicionGrupo)
        {


            var q = from a in DbUtil.Db.RendicionItems
                    where a.idgrupo == idRendicionGrupo
                    select new RendicionItemInfo
                    {
                        concepto = a.concepto,
                        descripcion = a.descripcion,
                        fecha = a.fecha,
                        idCajaRendicion = a.idRendicion,
                        idComparativo = a.idComparativo,
                        idInternal = a.idInternal,
                        idOrden = a.idOrden,
                        idTipoDocumento = a.idTipoDocumento,
                        numdocumento = a.numdocumento,
                        total = a.total,
                        totalStr = "{0:N}".Fmt(a.total),
                        fechaStr=a.fecha.ToShortDateString(),
                        tipodocumento =a.DocumentoTipo.descripcion
                    };


            return q.ToList();

        }

        //public IEnumerable<DocumentoCompraInfo> getDocumentoCompraItemList(int idRendicion)
        //{


        //    var q = from a in DbUtil.Db.RendicionItems
        //            where a.idRendicion == idRendicion
        //            select new DocumentoCompraInfo
        //            {
        //                fechaEmision=a.fecha,
        //                 fechaPago=a.fecha,
        //                 fechaVencimiento=a.fecha,
        //                  idInternal=a.idInternal,
        //                    idMoneda=a.Rendicion.Caja.idMoneda,
        //                     igvDoc=a.igvtotal,
        //                      impInafecto=0,
        //                       impISC=0,
        //                        importeNeto=a.total,
        //                         numDiasVen=0,
        //                          numDocumento=a.numdocumento,
        //                           Renta4ta=a.renta4ta,
        //                            RUC=a
                                    

                          
                         
        //            };


        //    return q.ToList();

        //}
        
        public List<DocumentoCompraInfo> GetDocumentoCompra(int idRendicion)
        {
            
            List<DocumentoCompraInfo> lista = new List<DocumentoCompraInfo>();
           var q= from a in DbUtil.Db.RendicionItems
                       where a.idRendicion==idRendicion
                       select a;

            foreach (var item in q )
            {

                 Moneda monedaAct = DbUtil.Db.Monedas.Single(p => p.idInternal == 4);
                    decimal tp = monedaAct.getTipoCambio(DbUtil.Db, item.fecha);
                    
                    decimal IGV =new Impuesto().GetIGV(DbUtil.Db, item.fecha);
                    //-----importante set  caja chica
                    string anexo = item.Rendicion.Caja.Empleado.dni;

                if (item.idTipoDocumento == 3) //Recibo Honorario
                {

                    string RUC=item.idProveedor!=null? item.Proveedor.ruc:"";

                    char tipoAnexo = ' ';
                    
                    var documento = new DocumentoCompraInfo(item.idInternal,
                                                            RUC,
                                                            0,
                                                            tipoAnexo,
                                                            'H',
                                                            item.idProveedor,
                                                            item.idEmpleado,
                                                            item.Proveedor.descripcion,
                                                            item.DocumentoTipo.pg_TIPODOC,
                                                            item.DocumentoTipo.descripcion,
                                                            item.idTipoDocumento,
                                                            item.numdocumento,
                                                            item.fecha,
                                                            item.fecha,
                                                            0,
                                                            item.fecha,
                                                            item.concepto,
                                                            item.Rendicion.Caja.idMoneda,
                                                            tp,
                                                            item.total,
                                                            0,
                                                            0, 0, IGV,
                                                            "Sist"
                                                            );

                    documento.SetTipoProvision("", "CAJ", 'T', anexo);

                      lista.Add(documento);

                }



            if (item.idTipoDocumento == 2)  //factura
            {
                 decimal totalIGV = 0;
               
                totalIGV=Math.Round(item.total * (1 + IGV / 100)-item.total,2);
               
                var documento = new DocumentoCompraInfo(item.idInternal,
                                            item.Proveedor.ruc,
                                            0,
                                            ' ' ,
                                            'P',
                                            item.idProveedor,
                                            item.idEmpleado,
                                            item.Proveedor.descripcion,
                                            item.DocumentoTipo.pg_TIPODOC,
                                            item.DocumentoTipo.descripcion,
                                            item.idTipoDocumento,
                                            item.numdocumento,
                                            item.fecha,
                                            item.fecha,
                                            0,
                                            item.fecha,
                                            item.concepto,
                                            item.Rendicion.Caja.idMoneda,
                                            tp,
                                            item.total,
                                            totalIGV,
                                            0,0,IGV,"sist"
                                            );

                documento.SetTipoProvision("", "CAJ", 'T', anexo);
                          lista.Add(documento);

             }

            if (item.idTipoDocumento == 4   //BOLETA DE VENTA
                            | item.idTipoDocumento == 5   //BOLETO DE AVION
                            | item.idTipoDocumento == 7   // NOTA DE DEBITO
                            | item.idTipoDocumento == 8   //TICKET MAQ. REGISTRADORA
                            | item.idTipoDocumento == 9   //RECIBO SERVICIOS PUBLICOS
                            | item.idTipoDocumento == 10   //BOLETO TRANSP. PUBLICO
                            | item.idTipoDocumento == 11   //BOLETO DE VIAJE TRASNPORTE
                            | item.idTipoDocumento == 17   //planilla movilidad   empleado
                            | item.idTipoDocumento==12  //RECIBO
                            )
                 {
                 
                var documento = new DocumentoCompraInfo(item.idInternal,
                                            item.idProveedor!=null?item.Proveedor.ruc:item.Empleado1.dni,
                                            0,
                                            ' ',
                                            item.idEmpleado!=null?'T':'P',
                                            item.idProveedor,
                                            item.idEmpleado ,
                                            item.idProveedor!=null?item.Proveedor.descripcion:item.Empleado.descripcion,
                                            item.DocumentoTipo.pg_TIPODOC,
                                            item.DocumentoTipo.descripcion,
                                            item.idTipoDocumento,
                                            item.numdocumento,
                                            item.fecha,
                                            item.fecha,
                                            0,
                                            item.fecha,
                                            item.concepto,
                                            item.Rendicion.Caja.idMoneda,
                                            tp,
                                            item.total,
                                            0,
                                            0,
                                            0,
                                            IGV,"sist"
                                            );

                documento.SetTipoProvision("", "CAJ", 'T', anexo);

                          lista.Add(documento);

                //planilla
                }
            }
                return lista;
        }  

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public IEnumerable<RendicionDepositoInfo> getRecepcionDepositoList(int idParent)
        {


            var q = from a in DbUtil.Db.RendicionDepositos
                    where a.idRendicion == idParent
                    select new RendicionDepositoInfo
                    {
                        fecha=a.fecha,
                        idInternal=a.idInternal,
                        idRendicion=a.idRendicion,
                        idTipoEntrega=a.idTipoEntrega,
                        numDocumento=a.numDocumento,
                        tipoEntregaStr=a.GrupoDatoitem.descripcion,
                        total=a.total,
                        totalStr="{0:N}".Fmt(a.total),
                        fechaStr=a.fecha.ToShortDateString()
                    };


            return q.ToList();

        }

      

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public decimal getSumRendicionDeposito(int idObra)
        {
            decimal total = 0;
            var q = (from a in DbUtil.Db.RendicionDepositos
                     where a.Rendicion.idObra == idObra
                     select a);

            if (q.Count() > 0)
            {
                total = q.Sum(p => p.total);
            }

            return total;

        }

        //[DataObjectMethod(DataObjectMethodType.Select, false)]
        //public decimal getRendicionInicio(int idRendicionAnterior)
        //{
        //    decimal total = 0;

        //    var q = (from a in DbUtil.Db.re
        //             where a.Rendicion.idAnterior == idRendicionAnterior
        //             select a);

        //    if (q.Count() > 0)
        //    {
        //        total = q.Sum(p => p.saldo.Value);
        //    }

        //    return total;

        //}

        //[DataObjectMethod(DataObjectMethodType.Select, false)]
        //public decimal getSumRendicionDepositoXRendicion(dbGestionDataContext _db, int idRendicion)
        //{
        //    decimal total = 0;
        //    var q = (from a in _db.RendicionDepositos
        //             where a.idRendicion == idRendicion
        //             select a);

        //    if (q.Count() > 0)
        //    {
        //        total = q.Sum(p => p.total);
        //    }

        //    return total;

        //}

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<RendicionGrupoInfo> getRendicionGrupoXRendicion(int idRendicion)
        {

            var q = (from a in DbUtil.Db.RendicionGrupos
                     where a.idRendicion == idRendicion
                     select new RendicionGrupoInfo
                     {
                         descripcion = a.descripcion,
                         idInternal = a.idInternal,
                         idRendicion = a.idRendicion,
                         total = (a.RendicionItems.Count() > 0) ? a.RendicionItems.Sum(p => p.total) : 0,

                     });


            return q.ToList();

        }


        //[DataObjectMethod(DataObjectMethodType.Select, false)]
        //public decimal getSumRendicionitemXRendicion(dbGestionDataContext _db,int idRendicion)
        //{
        //    decimal total = 0;

        //    var q = (from a in _db.RendicionItems
        //             where a.idRendicion == idRendicion
        //             select a);

        //    if (q.Count() > 0)
        //    {
        //        total = q.Sum(p => p.total);
        //    }
        //    return total;

        //}

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public decimal getSumRendicionitem(int idObra)
        {
            decimal total = 0;

            var q = (from a in DbUtil.Db.RendicionItems
                     where a.Rendicion.idObra == idObra
                     select a);

            if (q.Count() > 0)
            {
                total = q.Sum(p => p.total);
            }
            return total;

        }

       

        public bool updateAprobacion(int idRendicion)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                int idEmpleado = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                using (dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString))
                {
                    Empleado empleado = _db.Empleados.Single(p => p.idInternal == idEmpleado);
                    Rendicion rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);

                    int idEmpleadoEmisor = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                    var w = from a in _db.EmpleadoObras
                            where a.idObra == rendicion.idObra & a.idEmpleado == idEmpleado
                            select a.Rol;
                    if (w.Count() == 0)
                    {
                        throw new Exception("No tiene acceso a la Obra");
                    }

                    Rol rol = w.First();

                    DAL.Empresa empresa = _db.Empresas.Single(p => p.idInternal == rendicion.Obra.Proyecto.idEmpresa);


                    if (rendicion.idEstado == 41) //cerrado
                    {

                        throw new Exception("El Documento se encuentra Cerrado, verifique. ");
                    }

                    if (!rol.bitAprobarRecepcion)                    {
                        throw new Exception("El usuario no  esta habilitado para realizar la operacion");
                    }


                    //if (empresa.Logo == null)
                    //{
                    //    throw new Exception("Verifique logo de la empresa antes de Aprobar la Rendicion");
                    //}

                    //if (empresa.Logo.Trim() == String.Empty)
                    //{
                    //    throw new Exception("Verifique logo de la empresa antes de Aprobar la Rendicion");
                    //}


                    if (empleado.firma == null)
                    {
                        throw new Exception(String.Format("El usuario {0} no se tiene firma de autorizacion", empleado.descripcion));
                    }

                    if (empleado.firma.Trim() == String.Empty)
                    {
                        throw new Exception(String.Format("El usuario {0} no se tiene firma de autorizacion", empleado.descripcion));
                    }

                    rendicion.updateAutorizacion(_db, idEmpleado, empleado.descripcion, empleado.firma);
                    
                    
                    /// creamos el gasto de obra automaticamente
                    
                    OrdenCompraBL ocBOL = new OrdenCompraBL();
                    int idOrdenCompra=ocBOL.AddGastoFromRendicionCajaChica(_db, rendicion);
                    ocBOL.updateAutorizacion(_db,idOrdenCompra);


                }
                ts.Complete();
                return true;
            }




        }


        public bool updateDesAprobacion(int idRendicion)
        {
            bool result = false;
            //

            using (TransactionScope ts = new TransactionScope())
            {


                dbGestionDataContext _db =
                    new dbGestionDataContext(Parametros.strConnString);

                int idEmpleadoDesAprob = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                Rendicion rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);
                Empleado empleado = _db.Empleados.Single(p => p.idInternal == idEmpleadoDesAprob);

                if (rendicion.idEstado == 42)
                {
                    throw new Exception("La Rendicion Caja no puede ser DesAprobado, Existe Gasto de Obra");
                }
                if (rendicion.idEstado != 41)
                {
                    throw new Exception("La Rendicion Caja no puede ser DesAprobado, verifique Estado");
                }
                

                var we = from a in _db.EmpleadoObras
                         where a.idObra == rendicion.idObra & a.idEmpleado == idEmpleadoDesAprob
                         select a;

                if (we.Count() == 0)
                {
                    throw new Exception("No tiene permisos en Obra");
                }

                //buscamos que tenga un nivel de aprobacion
                Rol rolEmpleado = _db.Rols.Single(p => p.idInternal == we.First().idRol);
                if (!rolEmpleado.bitAprobarRecepcion)
                {
                    throw new Exception("No tiene permiso a Desaprobar la Rendicion de Caja");
                }
                
                rendicion.updateDesAutorizacion(_db);
                rendicion.updateDesRevisado(_db);

                OrdenCompraBL ocBOL = new OrdenCompraBL();
                var ordenCOmpra=_db.OrdenCompras.SingleOrDefault(p=>p.idRendicion==rendicion.idInternal);
                if (ordenCOmpra != null)
                {
                    ocBOL.deleteGastoObra(_db,ordenCOmpra.idInternal);
                }
                ts.Complete();
                result = true;



            }
            return result;
        }

        //---------------------
        public bool updateRevisor(int idRendicion)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                int idEmpleado = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                using (dbGestionDataContext _db = new dbGestionDataContext(Parametros.strConnString))
                {
                    Empleado empleado = _db.Empleados.Single(p => p.idInternal == idEmpleado);
                    Rendicion oc = _db.Rendicions.Single(p => p.idInternal == idRendicion);

                    if (oc.idEstado != 39) //cerrado
                    {

                        throw new Exception("Verifique Estado del documento");
                    }

                    

                    var w = from a in _db.EmpleadoObras
                            where a.idObra == oc.idObra & a.idEmpleado == idEmpleado
                            select a.Rol;
                    if (w.Count() == 0)
                    {
                        throw new Exception("No tiene acceso a la Obra");
                    }


                    if (empleado.firma == null)
                    {
                        throw new Exception(String.Format("El usuario {0} no se tiene firma de autorizacion", empleado.descripcion));
                    }

                    if (empleado.firma.Trim() == String.Empty)
                    {
                        throw new Exception(String.Format("El usuario {0} no se tiene firma de autorizacion", empleado.descripcion));
                    }


                    Rol rol = w.First();

                    if (!rol.bitRevisorRecepcion)
                    {
                        throw new Exception("No tiene permiso a Revisar la Rendicion de Caja");
                    }

                    DAL.Empresa empresa = _db.Empresas.Single(p => p.idInternal == oc.Obra.Proyecto.idEmpresa);

                    oc.updateRevisado(_db,
                        idEmpleado
                        , empleado.descripcion
                        ,empleado.firma);

                }
                ts.Complete();
                return true;
            }




        }
        public bool updateDesRevisor(int idRendicion)
        {
            bool result = false;
            //

            using (TransactionScope ts = new TransactionScope())
            {


                dbGestionDataContext _db =
                    new dbGestionDataContext(Parametros.strConnString);

                int idEmpleadoDesAprob = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

                Rendicion rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);
                Empleado empleado = _db.Empleados.Single(p => p.idInternal == idEmpleadoDesAprob);

                if (rendicion.idEstado != 40)
                {
                    throw new Exception("Verifique Estado del documento");
                }


                var we = from a in _db.EmpleadoObras
                         where a.idObra == rendicion.idObra & a.idEmpleado == idEmpleadoDesAprob
                         select a;

                if (we.Count() == 0)
                {
                    throw new Exception("No tiene permisos en Obra");
                }

                //buscamos que tenga un nivel de aprobacion
                Rol rolEmpleado = _db.Rols.Single(p => p.idInternal == we.First().idRol);
                if (!rolEmpleado.bitRevisorRecepcion)
                {
                    throw new Exception("No tiene permiso a Desaprobar la Rendicion de Caja");
                }

                rendicion.updateDesRevisado(_db);

                ts.Complete();
                result = true;



            }
            return result;
        }

        ////-----------------------
        // /// <summary>
        // /// Aprobacion de la rendicion de la caja
        // /// </summary>
        // /// <param name="idRendicion"></param>
        // /// <returns></returns>
        //public bool updateCerrar(int idRendicion)
        //{
        //    bool result = false;
        //    //

        //    using (TransactionScope ts = new TransactionScope())
        //    {


        //        dbGestionDataContext _db =
        //            new dbGestionDataContext(Parametros.strConnString);

        //        int idEmpleadoDesAprob = int.Parse(System.Web.HttpContext.Current.Session["idEmpleado"].ToString());

        //        Rendicion rendicion = _db.Rendicions.Single(p => p.idInternal == idRendicion);
        //        Empleado empleado = _db.Empleados.Single(p => p.idInternal == idEmpleadoDesAprob);

        //        if (rendicion.idEstado == 41)
        //        {
        //            throw new Exception("La Rendicion Caja no puede ser Aprobada, verifique Estado");
        //        }


        //        var we = from a in _db.EmpleadoObra
        //                 where a.idObra == rendicion.idObra & a.idEmpleado == idEmpleadoDesAprob
        //                 select a;

        //        if (we.Count() == 0)
        //        {
        //            throw new Exception("No tiene permisos en Obra");
        //        }

        //        //buscamos que tenga un nivel de aprobacion
        //        Rol rolEmpleado = _db.Rols.Single(p => p.idInternal == we.First().idRol);
        //        if (!rolEmpleado.bitAprobarRecepcion)
        //        {
        //            throw new Exception("No tiene permiso a Desaprobar la Rendicion de Caja");
        //        }
        //       // var saldos = new RendicionSaldo();



        //        decimal inicial =0;// (rendicion.idAnterior == null) ? 0 : this.getRendicionInicio(rendicion.idAnterior.Value);
        //        decimal ingreso = this.getSumRendicionDepositoXRendicion(_db, idRendicion);
        //        decimal egreso = this.getSumRendicionitemXRendicion(_db, idRendicion);
        //        decimal saldo = inicial + ingreso - egreso;
        //        saldos.SetAdd(_db,
        //                DateTime.Now,
        //                idRendicion,
        //                inicial,
        //                ingreso,
        //                egreso,
        //                saldo,
        //                idEmpleadoDesAprob);



        //        Rendicion nuevo = new Rendicion();
        //        nuevo.SetAdd(_db,
        //                    rendicion.idInternal,
        //                    nuevo.getCorrelativo(_db, rendicion.idObra),
        //                    rendicion.Caja.descripcion + " " + DateTime.Now.ToShortDateString(),
        //                     39,
        //                     rendicion.idObra,
        //                     rendicion.idCaja,
        //                     1);

        //        //genera nuevo registro para la siguiente Caja

        //        ts.Complete();
        //        result = true;



        //    }
        //    return result;
        //}


        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public List<RendicionRPT> loadRendicionRPT(int idRendicion)
        {

            Rendicion oc = DbUtil.Db.Rendicions.Single(p => p.idInternal == idRendicion);

            DAL.Empresa empresa = DbUtil.Db.Empresas.Single(p => p.idInternal == oc.Obra.Proyecto.idEmpresa);

            if (empresa.Logo == null)
            {
                throw new Exception("Verifique logo de la empresa ");
            }

            if (empresa.Logo.Trim() == String.Empty)
            {
                throw new Exception("Verifique logo de la empresa ");
            }



            
           



            string archivoLogo = empresa.Logo;
            string ArchivoFirmaAutoizado = oc.firmaAprobador;

            byte[] firma = new byte[200];

            if (ArchivoFirmaAutoizado == null)
            {
                firma = null;
            }
            else
            {
                string rutaFirma = System.Web.HttpContext.Current.Server.MapPath("../App_Data/Empleado/Firma/" + oc.idAprobacion.ToString() + "/" + ArchivoFirmaAutoizado);
                firma = UtilityExtensions.Util.FileToBytesImage(rutaFirma);

            }


            string ArchivoFirmaRevisado = oc.firmaRevisado;

            byte[] firmaRevisado = new byte[200];

            if (ArchivoFirmaRevisado == null)
            {
                firmaRevisado = null;
            }
            else
            {
                string rutaFirma = System.Web.HttpContext.Current.Server.MapPath("../App_Data/Empleado/Firma/" + oc.idRevisado.ToString() + "/" + ArchivoFirmaRevisado);
                firmaRevisado = UtilityExtensions.Util.FileToBytesImage(rutaFirma);

            }


            Empleado Custodio = DbUtil.Db.Empleados.Single(p => p.idInternal == oc.Caja.idCustodio);

            if (Custodio.firma == null)
            {
                throw new Exception("No existe Firma del Empleado: {0}".Fmt(Custodio.descripcion));
            }

            byte[] firmaRealizado = new byte[200];

            if (ArchivoFirmaRevisado == null)
            {
                firmaRealizado = null;
            }
            else
            {
                string rutaFirma = System.Web.HttpContext.Current.Server.MapPath("../App_Data/Empleado/Firma/" + oc.Caja.idCustodio.ToString() + "/" + Custodio.firma);

                if (!(System.IO.File.Exists(rutaFirma)))
                {
                    throw new Exception ("No existe firma del Empleado: {0}".Fmt(oc.Caja.Empleado.descripcion));
                }

                firmaRealizado = UtilityExtensions.Util.FileToBytesImage(rutaFirma);

            }



            string rutaLogo = System.Web.HttpContext.Current.Server.MapPath("../App_Data/Empresa/Logo/" + archivoLogo);
            if (!(System.IO.File.Exists(rutaLogo)))
            {
                throw new Exception("No existe Logo de la Empresa: {0}".Fmt(oc.Caja.Obra.Proyecto.Empresa.descripcion));
            }

            byte[] imagen = UtilityExtensions.Util.FileToBytesImage(rutaLogo);


            var q = from a in DbUtil.Db.RendicionItems
                    where a.idRendicion == idRendicion
                    select new RendicionRPT
                    {
                     
                        beneficiario = a.descripcion,
                        concepto = a.concepto.Length>=65? a.concepto.Substring(0, 65):a.concepto,
                        custodioStr = a.Rendicion.Caja.Empleado.descripcion,
                        direccion = a.Rendicion.Obra.direcccionEntrega,
                        numRecaudacion = a.Rendicion.numDocumento,
                        monedaStr="S/.",
                        fecha=a.fecha,
                        fechaCierre=a.fecha,

                        fondoAsignado=(a.Rendicion.RendicionDepositos.Count()>0)?a.Rendicion.RendicionDepositos.Sum(p=>p.total):0,
                        fondoGastado=(a.Rendicion.RendicionItems.Count()>0)?a.Rendicion.RendicionItems.Sum(p=>p.total):0,
                        

                        saldoAnt=a.Rendicion.saldoAnterior,
                        grupo=a.RendicionGrupo.descripcion,
                        idInternal=a.idInternal,
                        ingreso=0,
                        egreso = a.total,
                        numDocumento=a.numdocumento,
                        Obra=a.Rendicion.Obra.descripcion,
                        
                        tipodocumento=a.DocumentoTipo.abreviacion,
                        LogoEmpresa = imagen,
                                                                 /**cambie el ordern de firmas 21/01/2013 jcrlos**/
                        aprobado = firmaRevisado,
                        DNIAprob = a.Rendicion.idAprobacion != null ? a.Rendicion.Empleado1.dni : "",
                        nonbreAprob=a.Rendicion.Empleado.descripcion,

                        autorizado = firma,
                        DNIAutorizado = a.Rendicion.idRevisado != null ? a.Rendicion.Empleado.dni : "",
                        nombreAutorizado = a.Rendicion.Empleado1.descripcion,

                        realizado =firmaRealizado,
                        DNIRealizado = Custodio.dni,
                        nombreRealizado=Custodio.descripcion

                    };

            List<RendicionRPT> ListaRecaudacion = q.ToList();
            List<RendicionRPT> final = q.ToList();
            var deposito = DbUtil.Db.RendicionDepositos.Where(p => p.idRendicion == idRendicion);
            var SaldoAnterior = oc.saldoAnterior;
            if (SaldoAnterior != 0)
            {
                RendicionRPT nuevo = new RendicionRPT();
                RendicionRPT first = q.First();

                
                    nuevo = new RendicionRPT();
                    nuevo = (RendicionRPT)ListaRecaudacion.First().Clone();
                    nuevo.beneficiario = empresa.descripcion;
                    nuevo.concepto = "SALDO ANTERIOR";
                    nuevo.ingreso = SaldoAnterior;
                    nuevo.egreso = 0;
                    nuevo.fecha = (oc.fechaAprobacion==null?oc.fechaCre:oc.fechaAprobacion.Value);
                    nuevo.grupo = "_DEPOSITOS ";
                    nuevo.tipodocumento = "";
                    nuevo.numDocumento = "SALDO";//su forma de pago
                    nuevo.saldo = 0;
                    final.Add(nuevo);
            }            

            if (deposito.Count()>0)
            {
               if (ListaRecaudacion.Count()>0 )
                    {
                            RendicionRPT nuevo = new RendicionRPT();
                            RendicionRPT first = q.First();
                
                            foreach (var item in deposito.ToList())
                            {
                               nuevo = new RendicionRPT();
                               nuevo = (RendicionRPT)ListaRecaudacion.First().Clone();
                               nuevo.beneficiario = empresa.descripcion;
                               nuevo.concepto = item.GrupoDatoitem.descripcion+": "+ item.numDocumento;
                               nuevo.ingreso = item.total;
                               nuevo.egreso = 0;
                               nuevo.fecha = item.fecha;
                               nuevo.grupo = "_DEPOSITOS ";
                               nuevo.tipodocumento = "";
                               nuevo.numDocumento = item.GrupoDatoitem.descripcion;//su forma de pago
                               nuevo.saldo = 0;
                               final.Add(nuevo);
                            }
                
                    }
               else
               {
                //solo creamos su propias lineas de movimientos
               }
            }
            final = final.OrderBy(p => p.grupo).ToList();
            decimal  saldoAnterior=0;
            foreach (var item in final)
            {

                item.saldo = saldoAnterior + item.ingreso - item.egreso;
                saldoAnterior = item.saldo;

            }

            return final
                ;


        }




        int _count;

        public int Count(int idObra,
                         int startRowIndex,
                         int maximumRows,
                         string sortExpression)
        {
            return _count;
        }


        private IQueryable<RendicionInfo> ApplySelect_RendicionListInfo()
        {  
            var q = from a in DbUtil.Db.Rendicions
                    select new RendicionInfo
                    {

                        descripcion = a.descripcion,
                        totalAsignado = a.totalDeposito,
                        numDocumento = a.numDocumento,
                        totalGastado = a.toalIngreso,
                        idCaja = a.idCaja,
                        idInternal = a.idInternal,
                        idObra = a.idObra,
                        idEstado = a.idEstado,
                        estadoStr = a.GrupoDatoitem.descripcion,
                        totalSaldoAnterior = a.saldoAnterior,
                        moneda = a.Caja.Moneda.simbol,
                        custodio=a.Caja.Empleado.descripcion,
                        fechaVB = a.fechaRevisado==null?"":a.fechaRevisado.Value.ToShortDateString()
                    };

            return q;
        }
        private IQueryable<RendicionInfo> ApplySort(IQueryable<RendicionInfo> q, string sortExpression)
        {
            switch (sortExpression)
            {
                case "numDocumento":
                    q = q.OrderBy(b => b.numDocumento);
                    break;
                case "numDocumento DESC":
                    q = q.OrderByDescending(b => b.numDocumento);
                    break;
                case "fechaVB":
                    q = q.OrderBy(p => p.numDocumento).OrderBy(b => b.fechaVB);
                    break;
                case "fechaVB DESC":
                    q = q.OrderByDescending(p => p.numDocumento).OrderByDescending(b => b.fechaVB);
                    break;
                case "fechaStr":
                    q = q.OrderBy(b => b.fechaStr);
                    break;
                case "fechaStr DESC":
                    q = q.OrderByDescending(b => b.fechaStr);
                    break;

                case "custodio":
                    q = q.OrderBy(b => b.custodio);
                    break;
                case "custodio DESC":
                    q = q.OrderByDescending(b => b.custodio);
                    break;


                case "descripcion":
                    q = q.OrderBy(b => b.descripcion);
                    break;
                case "descripcion DESC":
                    q = q.OrderByDescending(b => b.descripcion);
                    break;

                case "estadoStr":
                    q = q.OrderBy(b => b.estadoStr);
                    break;
                case "estadoStr DESC":
                    q = q.OrderByDescending(b => b.estadoStr);
                    break;

                case "totalGastado":
                    q = q.OrderBy(b => b.totalGastado);
                    break;
                case "totalGastado DESC":
                    q = q.OrderByDescending(b => b.totalGastado);
                    break;
                //case "condicion":
                //    q = q.OrderBy(b => b.condicion);
                //    break;
                //case "condicion DESC":
                //    q = q.OrderByDescending(b => b.condicion);
                //    break;
                //case "numComparativo":
                //    q = q.OrderBy(b => b.numComparativo);
                //    break;
                //case "numComparativo DESC":
                //    q = q.OrderByDescending(b => b.numComparativo);
                //    break;
                default:
                    q = q.OrderByDescending(p => p.numDocumento);
                    break;
            }
            return q;
        }


        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public IEnumerable<RendicionInfo> getRecepcionList(int idCaja)
        {


            var q = ApplySelect_RendicionListInfo().Where(p => p.idCaja == idCaja);

            return q.OrderBy(p=>p.numDocumento).ToList();

        }

      


        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public IEnumerable<RendicionInfo> GetRendicionPendienteAprob(int idObra,
                                                                           int startRowIndex,
                                                                           int maximumRows,
                                                                           string sortExpression)
        {
            var q2 = this.ApplySelect_RendicionListInfo().Where(p=>p.idObra==idObra
                & p.idEstado==  40);

            _count = q2.Count();
            q2 = ApplySort(q2, sortExpression);
            q2 = q2.Skip(startRowIndex).Take(maximumRows);

            return q2;
        }


        
    }
}
